#ifndef AVALON_SERVERSOCKET_HPP
#define AVALON_SERVERSOCKET_HPP
#include "Avalon/IO/ServerConnection.hpp"
#include "Avalon/Network/TcpClientSocketChannel.hpp"

namespace boost {
namespace asio {
  class io_service;
}
namespace system {
  class error_code;
}
}

namespace Avalon {
namespace Network {

  /*! \class TcpServerSocket
   *  \brief Implements a server socket.
   */
  class TcpServerSocket : public IO::ServerConnection {
    public:

      //! Constructs a TcpServerSocket.
      /*!
        \param address The IP address to bind to.
      */
      TcpServerSocket(const IpAddress& address);

      virtual ~TcpServerSocket();

      virtual void Open();

      virtual void Accept(Out<Threading::Async<IO::Channel*> > channel);

      virtual bool IsOpen() const;

      virtual void Close();

      virtual void SetClosedSlot(const ClosedSlot& slot, Out<bool> isOpen);

    private:
      mutable boost::mutex m_mutex;
      IpAddress m_address;
      bool m_isOpen;
      boost::asio::io_service& m_ioService;
      void* m_acceptor;
      Threading::Async<IO::Channel*>* m_acceptResult;
      boost::shared_ptr<Detail::SocketType> m_socket;
      bool m_pendingClose;
      boost::condition_variable m_closedCondition;
      boost::function<void (const boost::system::error_code&)> m_acceptSlot;
      boost::shared_ptr<ClosedSlot> m_closedSlot;

      void OnAccept(const boost::system::error_code& error);
  };
}
}

#endif // AVALON_SERVERSOCKET_HPP
